The goal is to have a long message as input and produce an output which is much shorter called the hash or message digest. Furthermore, we want it to have certain properties.
We want the same input always produces the same output (deterministic)
There is a difference between hash function and cryptographic hash functions
Examples:
source: shattered.io
Secure Hash Algorithm (SHA) family, is a series of hashing algorithms. Ranging from SHA-0 to SHA-3. SHA-0 should never be used, it's advised to move from SHA-1 to SHA-2. SHA-3 is the most recent version, published in 2015.
In [ ]:
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
import base64 # to produce human readable encoding of the bytes
digest = hashes.Hash(hashes.SHA256(), backend=default_backend())
digest.update(b"PyCon")
digest.update(b"2017")
msg_digest = digest.finalize()
# Notice the output size of the digest
print ("msg_digest:", len(msg_digest), len(msg_digest) * 8)
print ("base64 encoding:", base64.b64encode(msg_digest))
print()
digest = hashes.Hash(hashes.SHA256(), backend=default_backend())
digest.update(b"PyCon2017")
msg_digest = digest.finalize()
# Notice the output size of the digest
print ("msg_digest:", len(msg_digest), len(msg_digest) * 8)
print ("base64 encoding:", base64.b64encode(msg_digest))
print()
digest = hashes.Hash(hashes.SHA256(), backend=default_backend())
digest.update(b"PyCon 2017")
msg_digest = digest.finalize()
# Notice the output size of the digest
print ("msg_digest:", len(msg_digest), len(msg_digest) * 8)
print ("base64 encoding:", base64.b64encode(msg_digest))
"Additional algorithms may also be available depending upon the OpenSSL library that Python uses on your platform. On most platforms the sha3_224(), sha3_256(), sha3_384(), sha3_512(), shake_128(), shake_256() are also available."
In [ ]:
import hashlib
sha256 = hashlib.sha256()
sha256.update(b"PyCon2017")
msg_digest = sha256.digest()
# Notice the output size of the digest
print ("msg_digest:", len(msg_digest), len(msg_digest) * 8)
print ("base64 encoding:", base64.b64encode(msg_digest))
$ HMAC(K,m) = H((K\oplus opad) || H((K \oplus ipad) || m))$
In [ ]:
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hmac, hashes
import os
import base64
hmc_key = k = os.urandom(16)
hmc = hmac.HMAC(hmc_key, hashes.SHA1(), default_backend())
hmc.update(b"PyCon2017")
hmc_sig = hmc.finalize()
print (base64.b64encode(hmc_sig))
In [ ]:
# Verification Successufl
hmc = hmac.HMAC(hmc_key, hashes.SHA1(), default_backend())
hmc.update(b"PyCon2017")
hmc.verify(hmc_sig)
In [ ]:
# Verification Fails
hmc = hmac.HMAC(hmc_key, hashes.SHA1(), default_backend())
hmc.update(b"PyCon2017")
hmc.verify(hmc_sig+b"1")